package com.yyx.jupiter.component;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Component;

import jakarta.annotation.Resource;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Component
public class RedisClient {
    @Resource(name = "genericRedisTemplate")
    private RedisTemplate<String, Object> genericRedisTemplate;

    public <T> T get(final String key, Class<T> clazz) {
        Object value = genericRedisTemplate.opsForValue().get(key);
        return clazz.isInstance(value) ? clazz.cast(value) : null;
    }

    public <T> List<T> multiGetValue(List<String> keys, Class<T> clazz) {
        List<Object> values = genericRedisTemplate.opsForValue().multiGet(keys);
        if (values == null) {
            return null;
        }
        List<T> result = new ArrayList<>();
        for (Object value : values) {
            result.add(clazz.isInstance(value) ? clazz.cast(value) : null);
        }
        return result;
    }

    public <T> Map<String, T> multiGet(List<String> keys, Class<T> clazz) {
        List<T> values = multiGetValue(keys, clazz);
        Map<String, T> result = new HashMap<>();
        for (int i = 0; i < values.size(); i++) {
            result.put(keys.get(i), values.get(i));
        }
        return result;
    }

    public void set(String key, Object value) {
        genericRedisTemplate.opsForValue().set(key, value);
    }

    public void setEx(String key, Object value, long timeout) {
        genericRedisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
    }

    public <T> T hGet(String key, String field, Class<T> clazz) {
        Object value = genericRedisTemplate.opsForHash().get(key, field);
        return clazz.isInstance(value) ? clazz.cast(value) : null;
    }

    public Map<String, Object> hGetAll(String key) {
        Map<Object, Object> entries = genericRedisTemplate.opsForHash().entries(key);
        Map<String, Object> result = new HashMap<>();
        entries.forEach((k, v) -> result.put(k.toString(), v));
        return result;
    }

    public Map<String, Map<String, Object>> multiHgetAll(List<String> keys) {
        Map<String, Map<String, Object>> values = new HashMap<>();
        for (String key : keys) {
            Map<String, Object> entries = hGetAll(key);
            values.put(key, entries);
        }
        return values;
    }

    public void hSet(String key, String field, Object value) {
        genericRedisTemplate.opsForHash().put(key, field, value);
    }

    public void hSetAll(String key, Map<String, Object> map) {
        genericRedisTemplate.opsForHash().putAll(key, map);
    }

    public void setTTL(String key, long timeout) {
        genericRedisTemplate.expire(key, timeout, TimeUnit.SECONDS);
    }

    public void ttl(String key) {
        genericRedisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    public List<Long> executeBF(RedisScript<List<Long>> script, List<String> keys, List<String> args) {
        return genericRedisTemplate.execute(script, keys, args.toArray());
    }
}
